<MudDataGrid T="Model"
             Virtualize="true"
             VirtualizeServerData="ServerDataFunc"
             RowClick="RowClicked"
             RowClassFunc="RowClassSelected"
             FixedHeader="true"
             Height="350px">
    <Columns>
        <PropertyColumn Property="x => x.Index" />
        <PropertyColumn Property="x => x.Column2" />
    </Columns>
</MudDataGrid>
<MudExpansionPanels Style="flex:1">
    <MudExpansionPanel Text="Show Events">
        @foreach (var message in _events)
        {
            <MudText Typo="@Typo.body2">@message</MudText>
        }
        @if (_events.Count > 0)
        {
            <div class="d-flex">
                <MudButton Class="mt-3" ButtonType="ButtonType.Button" Variant="Variant.Filled" OnClick="@StateHasChanged">Update</MudButton>
                <MudSpacer />
                <MudButton Class="mt-3" ButtonType="ButtonType.Button" Variant="Variant.Filled" OnClick="@(() => _events.Clear())">Clear</MudButton>
            </div>
        }
    </MudExpansionPanel>
</MudExpansionPanels>
<style>
    .mud-table-row-selected {
        background-color: rgb(from var(--mud-palette-primary) r g b / 0.25) !important;
    }
</style>

@code {

    public static string __description__ = @"The data grid should return correct line index when using VirtualizeServerData.";

    private int _selectedIndex;
    private readonly List<string> _events = [];
    private readonly IEnumerable<Model> _elements = Enumerable.Range(0, 20_000)
        .Select(i => new Model(i, $"Value_{i}"))
        .ToArray();

    /// <summary>
    /// Reloads the data from the server, with support for cancellation.
    /// </summary>
    private async Task<GridData<Model>> ServerDataFunc(GridStateVirtualize<Model> state, CancellationToken token)
    {
        try
        {
            // Simulate "loading data"
            await Task.Delay(500, token);

            IEnumerable<Model> data = _elements;

            data = data
                .Skip(state.StartIndex)
                .Take(state.Count)
                .ToList();

            // Return the data
            var result = new GridData<Model> { TotalItems = _elements.Count(), Items = data.ToArray() };
            _events.Add($"ServerDataFunc index : {state.StartIndex} (TotalItems : {result.TotalItems})");
            return result;
        }
        catch (Exception ex) when (ex is TaskCanceledException)
        {
            _events.Add($"ServerDataFunc index : {state.StartIndex} (Cancelled)");
            return new GridData<Model>
            {
                Items = [],
                TotalItems = 0,
            };
        }
    }

    private void RowClicked(DataGridRowClickEventArgs<Model> args)
    {
        // Virtualization didn't work well with storing item, because this item is recreated then the reference is different => use index instead or item discrimination
        _selectedIndex = args.RowIndex;
        _events.Add($"RowClicked index : {args.RowIndex}");
    }

    private string RowClassSelected(Model line, int index) => _selectedIndex == index
        ? "mud-table-row-selected"
        : string.Empty;

    public record Model(int Index, string Column2);
}